package com.hoshino.momochi.aspect;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Objects;

import javax.servlet.http.HttpServletRequest;

import com.google.common.collect.ImmutableList;
import com.hoshino.momochi.annotation.LimitCount;
import com.hoshino.momochi.service.RedisService;
import com.hoshino.momochi.util.JsonResponse;
import com.hoshino.momochi.util.IPUtil;
import com.hoshino.momochi.util.LuaScript;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Slf4j
@Aspect
@Component
public class LimitCountAspect {

    @Autowired
    private RedisService redisService;

    @Pointcut("@annotation(com.hoshino.momochi.annotation.LimitCount)")
    public void pointcut() {
        // do nothing
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        // 获取请求
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();

        // 获取注解参数
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        LimitCount annotation = method.getAnnotation(LimitCount.class);
        //注解名称
        String name = annotation.name();
        //注解key
        String key = annotation.key();
        //访问IP
        String ip = IPUtil.getIpAddr(request);
        //键过期时间
        int limitPeriod = annotation.period();
        //键过期次数
        int limitCount = annotation.count();

        // 执行 lua 脚本
        Number count = redisService.LimitLogin(annotation.prefix(), key, ip, limitCount, limitPeriod);

        log.info("IP:{} 第 {} 次访问keys为 {}，描述为 [{}] 的接口", ip, count, key + ip, name);

        if (count != null && count.intValue() <= limitCount) {
            return point.proceed();
        } else {
            return JsonResponse.success("接口访问超过限制");
        }
    }


}